var WMTSImageryProvider = function WMTSImageryProvider(description) {
    var trailingSlashRegex = /\/$/;
    var defaultCredit = new Cesium.Credit('WMTS');
    description = Cesium.defaultValue(description, {});
 
    var url = Cesium.defaultValue(description.url, 'http://localhost:88/wmts');
    if (!trailingSlashRegex.test(url)) {
         
    }
 
    this._url = url;
    this._fileExtension = Cesium.defaultValue(description.fileExtension, 'png');
    this._proxy = description.proxy;
    this._tileDiscardPolicy = description.tileDiscardPolicy;
 
     
    this._tilingScheme = new Cesium.WebMercatorTilingScheme({
        numberOfLevelZeroTilesX : 1,
        numberOfLevelZeroTilesY : 1
    });
 
    this._tileWidth = 512;
    this._tileHeight = 512;
 
    this._minimumLevel = Cesium.defaultValue(description.minimumLevel, 0);
    this._maximumLevel = Cesium.defaultValue(description.maximumLevel, 17);
    this._extent = Cesium.defaultValue(description.extent, this._tilingScheme.extent);
    this._rectangle = Cesium.defaultValue(description.rectangle, this._tilingScheme.rectangle);
 
    this._errorEvent = new Cesium.Event();
 
    this._ready = true;
 
    var credit = Cesium.defaultValue(description.credit, defaultCredit);
    if (typeof credit === 'string') {
        credit = new Cesium.Credit(credit);
    }
    this._credit = credit;
};
 function buildImageUrl(imageryProvider, col, row, level) {
            var labels = imageryProvider._tileMatrixLabels;
            var tileMatrix = Cesium.defined(labels) ? labels[level] : level.toString();
            var subdomains = imageryProvider._subdomains;
            var url;

            if (imageryProvider._url.indexOf('{') >= 0) {
                // resolve tile-URL template
                url = imageryProvider._url
                    .replace('{style}', imageryProvider._style)
                    .replace('{Style}', imageryProvider._style)
                    .replace('{TileMatrixSet}', imageryProvider._tileMatrixSetID)
                    .replace('{TileMatrix}', tileMatrix)
                    .replace('{TileRow}', row.toString())
                    .replace('{TileCol}', col.toString())
                    .replace('{s}', subdomains[(col + row + level) % subdomains.length]);
            }
            else {
                // build KVP request
                var uri = new Cesium.Uri(imageryProvider._url);
                var queryOptions = Cesium.queryToObject(Cesium.defaultValue(uri.query, ''));

                queryOptions = Cesium.combine(Cesium.defaultParameters, queryOptions);

                queryOptions.tilematrix = tileMatrix;
                queryOptions.layer = imageryProvider._layer;
                queryOptions.style = imageryProvider._style;
                queryOptions.tilerow = row;
                queryOptions.tilecol = col;
                queryOptions.tilematrixset = imageryProvider._tileMatrixSetID;
                queryOptions.format = imageryProvider._format;

                uri.query = Cesium.objectToQuery(queryOptions);

                url = uri.toString();
            }

            var proxy = imageryProvider._proxy;
            if (Cesium.defined(proxy)) {
                url = proxy.getURL(url);
            }

            return url;
        }
Cesium.defineProperties(WMTSImageryProvider.prototype, {
    url : {
        get : function() {
            return this._url;
        }
    },
 
    proxy : {
        get : function() {
            return this._proxy;
        }
    },
 
    tileWidth : {
        get : function() {
            if (!this._ready) {
                throw new Cesium.DeveloperError('tileWidth must not be called before the imagery provider is ready.');
            }
 
            return this._tileWidth;
        }
    },
 
    tileHeight: {
        get : function() {
            if (!this._ready) {
                throw new Cesium.DeveloperError('tileHeight must not be called before the imagery provider is ready.');
            }
 
            return this._tileHeight;
        }
    },
 
    maximumLevel : {
        get : function() {
            if (!this._ready) {
                throw new Cesium.DeveloperError('maximumLevel must not be called before the imagery provider is ready.');
            }
            return this._maximumLevel;
        }
    },
 
    minimumLevel : {
        get : function() {
            if (!this._ready) {
                throw new Cesium.DeveloperError('minimumLevel must not be called before the imagery provider is ready.');
            }
 
            return this._minimumLevel;
        }
    },
 
    tilingScheme : {
        get : function() {
            if (!this._ready) {
                throw new DeveloperError('tilingScheme must not be called before the imagery provider is ready.');
            }
            return this._tilingScheme;
        }
    },
 
    extent : {
        get : function() {
            if (!this._ready) {
                throw new Cesium.DeveloperError('extent must not be called before the imagery provider is ready.');
            }
            return this._extent;
        }
    },
    rectangle : {
        get : function() {
            if (!this._ready) {
                throw new DeveloperError('rectangle must not be called before the imagery provider is ready.');
            }
            return this._rectangle;
        }
    },
 
    tileDiscardPolicy : {
        get : function() {
            if (!this._ready) {
                throw new Cesium.DeveloperError('tileDiscardPolicy must not be called before the imagery provider is ready.');
            }
            return this._tileDiscardPolicy;
        }
    },
 
    errorEvent : {
        get : function() {
            return this._errorEvent;
        }
    },
 
    ready : {
        get : function() {
            return this._ready;
        }
    },
 
    credit : {
        get : function() {
            return this._credit;
        }
    }
});
 
WMTSImageryProvider.prototype.getTileCredits = function(x, y, level) {
    return undefined;
};
 
WMTSImageryProvider.prototype.requestImage = function(x, y, level) {
    if (!this._ready) {
        throw new Cesium.DeveloperError('requestImage must not be called before the imagery provider is ready.');
    }
 
    var url = buildImageUrl(this,  x, y, level);
    return Cesium.ImageryProvider.loadImage(this, url);
};

